package com.curluin.model;

import com.curluin.approximateShapes.ApproximateShape;
import com.curluin.approximateShapes.Contour;
import com.curluin.controll.Controller;
import com.curluin.math.MyMatrix;
import com.curluin.math.MyVector;
import com.curluin.scene.Cube;
import com.curluin.scene.Node;
import com.curluin.scene.TriangleMesh;

/**
 * @author Jo, Alex
 *
 */
public class Pinguin extends Moveable{

	public static final String LOG_TAG="Pinguin";
	private static final float WIGGLE=15;
	private boolean firstWiggle=true;
	private boolean wiggledLastToLeft;
	public static final float MAX_DIRECT_ANGLE=20;
	private TriangleMesh body,
	leftLeg, rightLeg,
	leftFoot, rightFoot,
	leftFlipper, rightFlipper,
	head, beak,
	leftEye, rightEye,
	leftPupil, rightPupil;

	/**
	 * Constructor
	 * @param position: starting position
	 * @param velocity: starting velocity (inclusive direction)
	 */
	public Pinguin(MyVector position,int positionMode, MyVector velocity){

		super(position, velocity,CONSITENCY_SOFT);
		debugColor=TriangleMesh.DARK_GRAY;
		if(this.getClass().equals(Pinguin.class)) initialize(position, positionMode);

	}

	public Pinguin(MyVector position, int positionMode, MyVector velocity, TriangleMesh torso, TriangleMesh head){
		super(torso,position, velocity,CONSITENCY_SOFT);
		MyVector headPos = MyVector.makeVector3(0, 0, -torso.innerSize.get(2)/2);
		head.setPosition(headPos, false, Node.CENTER);
		torso.addChild(head);
		this.head = head;
		debugColor=TriangleMesh.RED;
		if(this.getClass().equals(Pinguin.class)){ 
			initialize(position, positionMode);
			setRotation(MyVector.makeVector3(90, 0, 0));
			setHeadRotation(MyVector.makeVector3(-90, 0, 0));
		}

	}

	public Pinguin(MyVector position, int positionMode, MyVector velocity, TriangleMesh vis){

		super(vis,position, velocity,CONSITENCY_SOFT);
		debugColor=TriangleMesh.RED;
		if(this.getClass().equals(Pinguin.class)) initialize(position,positionMode);


	}

	@Override
	protected Node composeGraphics(){

		body = new Cube(MyVector.makeVector3(0, 0, 0), 10, 7, 20, TriangleMesh.DARK_GRAY);
		leftFlipper = new Cube(MyVector.makeVector3(-6, 0, 0), 2, 5, 12, TriangleMesh.DARK_GRAY);
		leftFlipper.rotate(0, -15, 0, Node.RESET);
		rightFlipper = new Cube(MyVector.makeVector3(6, 0, 0), 2, 5, 12, TriangleMesh.DARK_GRAY);
		rightFlipper.rotate(0, 15, 0, Node.RESET);
		leftLeg = new Cube(MyVector.makeVector3(-2, 0, 10), 1, 1, 5, TriangleMesh.BEAK_ORANGE);
		leftFoot = new Cube(MyVector.makeVector3(-1.2f, 0, 2.5f), 2, 1, 1, TriangleMesh.BEAK_ORANGE);
		leftFoot.rotate(0, 25, 0, Node.RESET);
		leftLeg.addChild(leftFoot);
		rightLeg = new Cube(MyVector.makeVector3(2, 0, 10), 1, 1, 5, TriangleMesh.BEAK_ORANGE);
		rightFoot = new Cube(MyVector.makeVector3(1.2f, 0, 2.5f), 2, 1, 1, TriangleMesh.BEAK_ORANGE);
		rightFoot.rotate(0, -25, 0, Node.RESET);
		rightLeg.addChild(rightFoot);
		head = new Cube(MyVector.makeVector3(0, 0, -12.5f), 5, 5, 5, TriangleMesh.DARK_GRAY);
		beak = new Cube(MyVector.makeVector3(0, 0, -3.5f), 1, 1, 2, TriangleMesh.BEAK_ORANGE);
		head.addChild(beak);
		leftEye = new Cube(MyVector.makeVector3(-1.3f, 2.6f, -1.8f), 1.2f, 0.2f, 1.2f, TriangleMesh.SNOW_WHITE);
		leftPupil = new Cube(MyVector.makeVector3(0, 0.2f, -0.1f), 0.4f, 0.2f, 0.4f, TriangleMesh.BLACK);
		leftEye.addChild(leftPupil);
		rightEye = new Cube(MyVector.makeVector3(1.3f, 2.6f, -1.8f), 1.2f, 0.2f, 1.2f, TriangleMesh.SNOW_WHITE);
		rightPupil = new Cube(MyVector.makeVector3(0, 0.2f, -0.1f), 0.4f, 0.2f, 0.4f, TriangleMesh.BLACK);
		rightEye.addChild(rightPupil);
		head.addChild(leftEye);
		head.addChild(rightEye);
		body.addChild(leftFlipper);
		body.addChild(rightFlipper);
		body.addChild(leftLeg);
		body.addChild(rightLeg);
		body.addChild(head);
		body.scale(0.5f);

		return body;
	}

	@Override
	protected ApproximateShape initializeApproximateShape() {
//				Rectangle r = new Rectangle(node);
		Contour r = new Contour(30, node);
		//		Ellipse r = new Ellipse(this.node);
		return r;
	}

	/**
	 * Acceleration by wipes in Runway phase
	 * @param factor degree of additional acceleration
	 */
	public void accelerate(float increase){
		//		Log.e(LOG_TAG, "Velocity:"+velocity.toString());
		MyVector velWithoutFall =MyVector.makeVector3(velocity.get(0), 0, Math.min(velocity.get(2), -Controller.minVelocity)); 
		float newLength = velWithoutFall.getNorm()+increase;
		velWithoutFall.normalize();
		velWithoutFall=velWithoutFall.multiply(newLength);
		velWithoutFall.set(1, velocity.get(1));
		velocity=velWithoutFall;
		//		velocity.set(2, velocity.get(2)-increase);
//		Log.e(LOG_TAG, "Mycenter: "+position+" NodeCenter "+node.getCenter()+" Scandata Center "+((Rectangle)shape).center);

	}


	/**
	 * Rotation adjustment by wipes in Runway phase
	 * @param degree of additional rotation
	 */
	public void direct(float angle){
		
		if(Controller.gamePhase != Controller.GAMEPHASE_RUNWAY) return;
		
		float rot=(angle<0)?Math.max(angle, -MAX_DIRECT_ANGLE):Math.min(angle, MAX_DIRECT_ANGLE);
		//rotate Velocity vector around y axis
		MyVector axis = MyVector.makeVector3(0, 1, 0);
		velocity = MyMatrix.getRotationMatrix(axis, -rot/180f*(float)Math.PI).multiply(velocity);
		//rotate visualization
		node.rotate(0, rot, 0, Node.ADDITIONALLY);
		
		}
	
	/**
	 * "Animates" wiggle of Pinguin
	 * @param wiggleToLeft
	 */
	public void wiggle(boolean wiggleToLeft){
		float angle = WIGGLE;
		//ensure overallAngle is equal to WIGGLE
		if(!firstWiggle) angle*=2;
		else firstWiggle = false;
		//ensure alternating wiggling
		if(wiggleToLeft == wiggledLastToLeft) wiggleToLeft=!wiggleToLeft;
		//rotate visualization
		node.rotate(0, 0, wiggleToLeft? -angle : angle, Node.ADDITIONALLY);
		wiggledLastToLeft = wiggleToLeft;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Pinguin [velocity=" + velocity + ", position=" + position + "]";
	}

	public void setHeadRotation(MyVector rotation) {
		head.rotate(rotation, false);
	}

	//	public int getGamePhase() {
	//		float gamePhase = 0;
	//		for(Ground ground : gridFieldsWithHighestGrounds){
	//			gamePhase += gf.getGround().getGamePhase();
	//		}
	//		return Math.round(gamePhase/gridFieldsWithHighestGrounds.size());
	//		//return actGround.getGamePhase();		
	//	}
}
